#include "func.h"
#include "image.h"
#include <math.h>

struct A {
	int x, y, data;
};

class ai {
	private:
		A dp[225]; // 记录每个点的分数
		int me, human; //记录player
		// 方向从左上开始，顺时针一直到左边
		int navigator[8][2] = {{-1,-1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}}; 
	public:
		ai(int pl) {
			me = pl;
			human = me == 1 ? 2 : 1;
			srand(time(0));
		}
		
		// 为每个x, y 点打分的函数（太过于混乱，已经丢弃）
		int check(const char bd[17][17], int x, int y) {
			int r1 = 27, r2 = 7, r3 = 177;
			int res[8][3] = {0}, i, r, ans = 0;
	
			i = 1;
			if (y + 1 <= 15) {
				if (bd[x][y + 1] == me)
					r = r1, res[0][2] = me;
				else if (bd[x][y + 1])
					r = r2, res[0][2] = human;
				else
					r = 0;
				if (r)
					while (y + i <= 15) {
						if (bd[x][y + i] == bd[x][y + 1])
							i++;
						else
							break;
					}
//            if(y+i <= 15 && bd[x][y+i] == 0) {
//            	if(y+1+i <= 15 && bd[x][y+i+1] == 0) r0[0] = 0;
//				else if(y+1+i <= 15 && bd[x][y+i+1] == chess) r0[0] = 1;
//				else if(y+1+i <= 15 && bd[x][y+i+1] != chess) r0[0] = -3;
//			}

			}
			if (i - 1 )
				res[0][0] =  i - 1, res[0][1] = r;
			if (i > 2) {
				if (y + 1 + i <= 15 && bd[x][y + i + 1] != 0)
					res[0][1] -= r3 ;
			}
			i = 1;
			if (y + 1 <= 15 && x + 1 <= 15) {
				if (bd[x + 1][y + 1] == me)
					r = r1, res[1][2] = me;
				else if (bd[x + 1][y + 1])
					r = r2, res[1][2] = human;
				else
					r = 0;
				if (r)
					while (y + i <= 15 && x + i <= 15) {
						if (bd[x + i][y + i] == bd[x + 1][y + 1])
							i++;
						else
							break;
					}
//            if(y+i <= 15 && x+i <= 15 && bd[x+i][y+i] == 0){
//            	if(y+1+i <= 15 && x+1+i <= 15 && bd[x+i+1][y+i+1] == 0) r0[1] = 0;
//            	else if(y+1+i <= 15 && x+1+i <= 15 && bd[x+i+1][y+i+1] == chess) r0[1] = 1;
//            	else if(y+1+i <= 15 && x+1+i <= 15 && bd[x+i+1][y+i+1] != chess) r0[1] = -3;
//			}
			}
			res[1][0] =  i - 1, res[1][1] = r;
			if (i > 2) {
				if (y + 1 + i <= 15 && x + 1 + i <= 15 && bd[x + i + 1][y + i + 1] != 0)
					res[1][1] -= r3 ;
			}
			i = 1;
			if (x + 1 <= 15) {
				if (bd[x + 1][y] == me)
					r = r1, res[2][2] = me;
				else if (bd[x + 1][y])
					r = r2, res[2][2] = human;
				else
					r = 0;
				if (r)
					while (x + i <= 15) {
						if (bd[x + i][y] == bd[x + 1][y])
							i++;
						else
							break;
					}
//            if(x+i <= 15 && bd[x+i][y] == 0){
//            	if(bd[x+i+1][y] == 0 && x+1+i <= 15) r0[2] = 0;
//            	else if(x+1+i <= 15 && bd[x+i+1][y] == chess) r0[2] = 1;
//            	else if(x+1+i <= 15 && bd[x+i+1][y+i+1] != chess) r0[2] = -3;
//			}
			}
			res[2][0] =  i - 1, res[2][1] = r;
			if (i > 2) {
				if (bd[x + i + 1][y] != 0 && x + 1 + i <= 15)
					res[2][1] -= r3;
			}
			i = 1;
			if (x + 1 <= 15 && y - 1 >= 1) {
				if (bd[x + 1][y - 1] == me)
					r = r1, res[3][2] = me;
				else if (bd[x + 1][y - 1])
					r = r2, res[3][2] = human;
				else
					r = 0;
				if (r)
					while (x + 1 <= 15 && y - 1 >= 1) {
						if (bd[x + i][y - i] == bd[x + 1][y - 1])
							i++;
						else
							break;
					}
//            if(x+i <= 15 && y-i >= 1 && bd[x+i][y-i] == 0)
//				if(bd[x+i+1][y-i-1] == 0 && x+1+i <= 15 && y-1-i >= 1) r0[3] = 0;
//				else if(bd[x+i+1][y-i-1] == chess && x+1+i <= 15 && y-1-i >= 1) r0[3] = 1;
//            	else if(bd[x+i+1][y-i-1] != chess && x+1+i <= 15 && y-1-i >= 1) r0[3] = -3;
			}
			res[3][0] =  i - 1, res[3][1] = r;
			if (i > 2) {
				if (bd[x + i + 1][y - i - 1] != 0 && x + 1 + i <= 15 && y - 1 - i >= 1)
					res[3][1] -= r3 ;
			}
			i = 1;
			if (y - 1 >= 1) {
				if (bd[x][y - 1] == me)
					r = r1, res[4][2] = me;
				else if (bd[x][y - 1])
					r = r2, res[4][2] = human;
				else
					r = 0;
				if (r)
					while (y - 1 >= 1) {
						if (bd[x][y - i] == bd[x][y - 1])
							i++;
						else
							break;
					}
//            if(y-i >= 1 && bd[x][y-i] == 0)
//				if(bd[x][y-i-1] == 0 && y-1-i >= 1) r0[4] = 0;
//				else if(bd[x][y-i-1] == chess && y-1-i >= 1) r0[4] = 1;
//            	else if(bd[x][y-i-1] != chess && y-1-i >= 1) r0[4] = -3;
			}
			res[4][0] =  i - 1, res[4][1] = r;
			if (i > 2) {
				if (bd[x][y - i - 1] != 0 && y - 1 - i >= 1)
					res[4][1] -= r3 ;
			}

			i = 1;
			if (x - 1 >= 1 && y - 1 >= 1) {
				if (bd[x - 1][y - 1] == me)
					r = r1, res[5][2] = me;
				else if (bd[x - 1][y - 1])
					r = r2, res[5][2] = human;
				else
					r = 0;
				if (r)
					while (x - 1 >= 1) {
						if (bd[x - i][y - i] == bd[x - 1][y - 1])
							i++;
						else
							break;
					}
				if (i > 2) {
					if (bd[x - i - 1][y - i - 1] != 0 && x - 1 - i >= 1 && y - 1 - i >= 1)
						res[5][1] -= r3 ;
				}
//            if(y-i >= 1 && x-i >= 1 && bd[x-i][y-i] == 0)
//				if(bd[x-i-1][y-i-1] == 0 && x-1-i >= 1 && y-1-i >= 1) r0[5] = 0;
//				else if(bd[x-i-1][y-i-1] == chess && x-1-i >= 1 && y-1-i >= 1) r0[5] = 1;
//            	else if(bd[x-i-1][y-i-1] != chess && x-1-i >= 1 && y-1-i >= 1) r0[5] = -3;
			}
			res[5][0] =  i - 1, res[5][1] += r;
			i = 1;
			if (x - 1 >= 1) {
				if (bd[x - 1][y] == me)
					r = r1, res[6][2] = me;
				else if (bd[x - 1][y])
					r = r2, res[6][2] = human;
				else
					r = 0;
				if (r)
					while (x - 1 >= 1) {
						if (bd[x - i][y] == bd[x - 1][y])
							i++;
						else
							break;
					}
				if (i > 2) {
					if (bd[x - i - 1][y] != 0 && x - 1 - i >= 1)
						res[6][1] -= r3 ;
				}
//            if(x-i >= 1 && bd[x-i][y] == 0)
//				if(bd[x-i-1][y] == 0 && x-1-i >= 1) r0[6] = 0;
//				else if(bd[x-i-1][y] == chess && x-1-i >= 1) r0[6] = 1;
//            	else if(bd[x-i-1][y] != chess && x-1-i >= 1) r0[6] = -3;
			}
			res[6][0] =  i - 1, res[6][1] += r;
			i = 1;
			if (x - 1 >= 1 && y + 1 <= 15) {
				if (bd[x - 1][y + 1] == me)
					r = r1, res[7][2] = me;
				else if (bd[x - 1][y + 1])
					r = r2, res[7][2] = human;
				else
					r = 0;
				if (r)
					while (x - 1 >= 1 && y + 1 <= 15) {
						if (bd[x - i][y + i] == bd[x - 1][y + 1])
							i++;
						else
							break;
					}
				if (i > 2) {
					if (bd[x - i - 1][y + i + 1] != 0 && x - 1 - i >= 1 && y + 1 + i <= 15)
						res[7][1] -= r3;
				}
//            if(x-i >= 1 && y+i <= 15 && bd[x-i][y+i] == 0)
//				if(bd[x-i-1][y+i+1] == 0 && x-1-i >= 1 && y+1+i <= 15) r0[7] = 0;
//				else if(bd[x-i-1][y+i+1] == chess && x-1-i >= 1 && y+1+i <= 15) r0[7] = 1;
//            	else if(bd[x-i-1][y+i+1] != chess && x-1-i >= 1 && y+1+i <= 15) r0[7] = -3;
			}
			res[7][0] =  i - 1, res[7][1] += r;

			for (i = 0; i < 4; i++) {
				if (res[i][2] == res[i + 4][2] && res[i][2]) {
					res[i][0] += res[i + 4][0];
					res[i + 4][0] = 0;
				}
			}

			for (i = 0; i < 8; i++) {
				if (res[i][0] == 3 && res[i][2] == me && res[(i + 4) % 8][2] != human)
					res[i][1] += 35;
				if (res[i][0] == 3 && res[i][2] == me && res[(i + 4) % 8][2] == human)
					res[i][1] -= 10;
				if (res[i][0] == 3 && res[i][2] == human && res[(i + 4) % 8][2] == human)
					res[i][1] += 100;
				if (res[i][0] == 3 && res[i][2] == human && res[(i + 4) % 8][2] != human)
					res[i][1] += 20;
				if (res[i][0] == 4 && res[i][2] == me)
					res[i][1] += 1000;
				if (res[i][0] == 4)
					res[i][1] += 800;
			}

			for (i = 0; i < 8; i++) {
				res[i][1] *= res[i][0]; 
			}
			for (i = 0; i < 8; i++)
				ans += res[i][1];
			return ans;
		}

		// 获取得分最高的点
		A getMax(A q[]) {
			A m = q[0];
			for (int i = 1; i < 225; i++){
				if (q[i].data > m.data) m = q[i];
				else if (q[i].data == m.data && q[i].data != 0){
					if (rand()%100 < 25) m = q[i];
				}
			}
			return m;
		}
	

		// 下棋函数
		void aidraw(char board[17][17]) {
			// 初始化每个点的分数
			for (int i = 0; i < 225; i++)
				dp[i].data = 0;
			
			// 通过check打分函数得出每个点得分数
			for (int i = 1; i <= 15; i++) {
				for (int j = 1; j <= 15; j++) {
					if (!board[i][j]){
						dp[(i - 1) * 15 + j - 1].data = check_v2(board, i, j);
						dp[(i - 1) * 15 + j - 1].x = i;
						dp[(i - 1) * 15 + j - 1].y = j;
					}
				}
			}
			
			// 获取最佳点并修改棋盘
			A ans = getMax(dp);
			int x = ans.x, y = ans.y;
			board[x][y] = me;
			prx = x, pry = y;
		}
	
		// 新的打分函数
		int check_v2(const char bd[17][17], int x, int y) {
			// 每个点可以有八个方向， 由 0 - 7 表示
			// direct[i][0] 表示方向i的相同棋子个数，
			// direct[i][1] 表示方向i的相同棋子类型
			// direct[i][2] 表示方向i的棋子末端情况，方向i没有棋子：0，有棋子且末端为空：1，有棋子末端不空或者是边界：2
			int direct[8][3] = {0};
			// 计算八个方向的情况
			check_line(bd, x, y, direct, 0);
			check_line(bd, x, y, direct, 1);
			check_line(bd, x, y, direct, 2);
			check_line(bd, x, y, direct, 3);
			check_line(bd, x, y, direct, 4);
			check_line(bd, x, y, direct, 5);
			check_line(bd, x, y, direct, 6);
			check_line(bd, x, y, direct, 7);
			// 为空的情况赋值0
			for (int i = 0; i < 8; i++) if(!direct[i][1]) direct[i][0] = 0, direct[i][2] = 0;
			
			// 总分和三个不同的权重
			int sum = 0;
			int w1 = 66, w2 = 22, w3 = 7;
			
			// 前4个方向打分
			for (int i = 0; i < 4; i++){
				if (direct[i][1] == 0) continue; // 为空则继续
				else if (direct[i][1] == direct[i+4][1]) direct[i+4][0] += direct[i][0]; // 相对的方向有相同棋子则留给相对方向计算
				else {
					// 此时相对方向没有棋子或者棋子不相同
					// 有四个相同棋子的情况
					if (direct[i][0] == 4 && direct[i][1] == me){
						sum += 99999999;
					}else if (direct[i][0] == 4 && direct[i][1] == human){
						sum += 11111111;
					}
					// 相对方向没有棋子且本方向末端为空
					else if (direct[i][2] == 1 && direct[i+4][2] == 0){
						// 此时有三个相同棋子的情况，此时 sum += pow(w1, direct[i][0]) 不影响结果
						if (direct[i][0] == 3 && direct[i][1] == me) sum += 5555555;
						else if(direct[i][0] == 3 && direct[i][1] == human) sum += 1111111;
						// 没有三个相同棋子时
						sum += pow(w1, direct[i][0]);
					}
					// 相对方向没有棋子且本方向末端有棋子，或者相对方向有棋子且本方向末端没有棋子的情况
					else if ((direct[i][2] == 2 && direct[i+4][2] == 0) || 
						(direct[i][2] == 1 && direct[i+4][2] != 0)){
						sum += pow(w2, direct[i][0]);
					}else{
						// 两边都有棋子
						sum += pow(w3, direct[i][0]);
					}
				}
			}
			
			for (int i = 4; i < 8; i++){
				if (direct[i][1] == 0) continue;
				else if (direct[i][1] == direct[i-4][1]){ // 相对方向有棋子
					// 四个棋子情况
					if (direct[i][0] == 4 && direct[i][1] == me){
						sum += 99999999;
					}else if (direct[i][0] == 4 && direct[i][1] == human){
						sum += 11111111;
					}
					// 两边末端都为空的情况
					else if (direct[i][2] == 1 && direct[i-4][2] == 1){
						if (direct[i][0] == 3 && direct[i][1] == me) sum += 5555555;
						else if(direct[i][0] == 3 && direct[i][1] == human) sum += 1111111;
						sum += pow(w1, direct[i][0]);
					}
					// 有一边末端不为空的情况
					else if (direct[i][2] == 1 || direct[i-4][2] == 1){
						sum += pow(w2, direct[i][0]);
					}else {
						// 两边末端都不为空
						sum += pow(w3, direct[i][0]);
					}
				}else {
					// 同 330 行
					if (direct[i][0] == 4 && direct[i][1] == me){
						sum += 99999999;
					}else if (direct[i][0] == 4 && direct[i][1] == human){
						sum += 11111111;
					}else if (direct[i][2] == 1 && direct[i-4][2] == 0){
						if (direct[i][0] == 3 && direct[i][1] == me) sum += 5555555;
						else if(direct[i][0] == 3 && direct[i][1] == human) sum += 1111111;
						sum += pow(w1, direct[i][0]);
					}else if ((direct[i][2] == 2 && direct[i-4][2] == 0) || 
						(direct[i][2] == 1 && direct[i+4][2] != 0)){
						sum += pow(w2, direct[i][0]);
					}else{
						sum += pow(w3, direct[i][0]);
					}
				}
			}
			return sum;
		}
		
		// 检测 0 - 7 方向的棋子个数以及末端情况
		void check_line(const char bd[17][17], int x, int y, int direct[][3], int idx){
			int x1 = x+navigator[idx][0] , y1 = y+navigator[idx][1];
			int px1 = x1, py1 = y1;
			for(int i=1; x1 <= 15 && x1 >= 1 && y1 <= 15 && y1 >= 1; i++){
				if (!bd[x1][y1]){
					direct[idx][0] = i-1;
					direct[idx][1] = bd[px1][py1];
					direct[idx][2] = 1;
					break;
				}else if (i > 1 && bd[x1][y1] != bd[px1][py1]) {
					direct[idx][0] = i-1;
					direct[idx][1] = bd[px1][py1];
					direct[idx][2] = 2;
					break;
				}
				x1 = x1+navigator[idx][0] , y1 = y1+navigator[idx][1];
			}
			if (x1 > 15 || x1 < 1 || y1 > 15 || y1 < 1) direct[idx][2] = 2;
		}
};
